<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://s4.ssl.qhres.com/!928fb688/spritejs.min.js"></script>
  <style>
    html, body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      overflow: hidden;
    }

    #scene-container {
      width: 100%;
      height: 100%;
      background: #1eac61;
    }

    #scene-container.extend {
      background-color: #eee;
      transition: background-color 2s;
    }
  </style>
</head>
<body>
  <div id="scene-container"></div>
  <script>
  (async function () {
    const {Scene, Sprite, Group, Label, Path} = spritejs
    const scene = new Scene('#scene-container', {
      viewport: ['auto', 'auto'],
      resolution: [3840, 2160],
      stickMode: 'width',
    })

    await scene.preload([
      'https://p5.ssl.qhimg.com/t01f47a319aebf27174.png',
      'https://s3.ssl.qhres.com/static/a6a7509c33a290a6.json',
    ])

    const fglayer = scene.layer('fglayer')

    function showLogoText(text, pos, posList, delay = 0) {
      const els = []
      for(let i = 0; i < text.length; i++) {
        const letter = text.charAt(i),
          x = posList[i]

        const letterEl = new Sprite(`letter-${letter}.png`)
        letterEl.attr({pos: [pos[0] + x, pos[1]]})
        if(letter === 'j') {
          letterEl.attr({zIndex: 20})
        }
        els.push(letterEl)
        fglayer.append(letterEl)
      }
      return els
    }

    function showIntroText(text, pos) {
      const introText = new Group()
      introText.attr({
        anchor: 0.5,
        pos,
        size: [720, 80],
        opacity: 0.8,
        // bgcolor: 'rgba(0, 0, 0, 0.3)',
      })
      fglayer.append(introText)

      ;[...text].forEach((char, i) => {
        const label = new Label(char)
        label.attr({
          pos: [i * 80, 0],
          font: '54px "宋体"',
          fillColor: '#fff',
        })
        introText.append(label)
      })

      return introText
    }

    function showHuanHuan(...pos) {
      const huanhuanGroup = new Group()
      huanhuanGroup.attr({
        anchor: 0.5,
        pos,
        rotate: 30,
        size: [200, 320],
        zIndex: 100,
        // bgcolor: 'red',
      })
      fglayer.append(huanhuanGroup)

      const huanhuan = new Sprite('huanhuan.png')
      huanhuan.attr({
        pos: [0, 0],
      })
      huanhuanGroup.append(huanhuan)

      const huanhuanFire = new Path()
      huanhuanFire.attr({
        path: {d: 'M0,0Q-1,12,5,36Q30,22,30,0z', transform: {scale: 2}},
        anchor: [0, 0],
        fillColor: '#FEE139',
        pos: [46, 220],
        lineWidth: 6,
        strokeColor: '#FB6F4A',
        zIndex: -1,
        rotate: -5,
      })
      huanhuanGroup.append(huanhuanFire)

      // random burn fire
      let fx = 5,
        fy = 6

      fglayer.timeline.setInterval(() => {
        const deltaX = Math.floor(Math.random() * 3) - 1, // -1 0 1,
          deltaY = Math.floor(Math.random() * 3) - 1

        fx += deltaX
        if(fx < 0) fx = 0
        if(fx > 15) fx = 15

        fx += deltaY
        if(fy < 0) fy = 0
        if(fy > 20) fy = 20

        const q1 = [-1, 12, -5 + fx, 30 + fy]
        const q2 = [30, 22, 30, 0]
        const d = `M0,0Q${q1}Q${q2}z`
        huanhuanFire.attr({
          path: {d, transform: {scale: 2}},
        })
      }, 100)

      huanhuanGroup.on('mouseenter', (evt) => {
        huanhuan.textures = 'huanhuan2.png'
      })

      huanhuanGroup.on('mouseleave', (evt) => {
        huanhuan.textures = 'huanhuan.png'
      })
  
      const y0 = pos[1]
      huanhuanGroup.animate([
        {y: y0},
        {y: y0 + 10},
        {y: y0},
        {y: y0 - 10},
        {y: y0},
      ], {
        duration: 2000,
        iterations: Infinity,
      })

      return huanhuanGroup
    }

    function showGuanGuan(...pos) {
      const guanguan = new Sprite('guanguan1.png')
      guanguan.attr({
        anchor: 0.5,
        scale: [-1, 1],
        pos,
        zIndex: 100,
      })
      fglayer.append(guanguan)

      guanguan.on('mouseenter', (evt) => {
        if(guanguan.textures[0].id !== 'guanguan3.png') {
          guanguan.textures = ['guanguan2.png']
          guanguan.attr({rotate: 30})
        }
      })
      guanguan.on('mouseleave', (evt) => {
        if(guanguan.textures[0].id !== 'guanguan3.png') {
          guanguan.textures = ['guanguan1.png']
          guanguan.attr({rotate: 0})
        }
      })

      return guanguan
    }

    showLogoText('spritejs', [1108, 682], [0, 256, 500, 760, 848, 1078, 1286, 1488], 200)
    showIntroText('跨平台绘图对象模型', [2000, 1110])
    const huanhuan = showHuanHuan(1080, 650)
    const guanguan = showGuanGuan(2380, 1350)

    async function displayText(text, pos, attrs, delay = 0) {
      const group = new Group()
      group.attr({
        anchor: attrs.anchor || 0,
        pos,
      })
      fglayer.append(group)

      let x = 0
      const y = 0
      attrs.anchor = 0

      /* eslint-disable no-restricted-syntax */
      for(const t of [...text]) {
        const label = new Label(t)
        label.attr(attrs)
        group.append(label)
  
        label.attr({
          pos: [x, y],
        })
        x += label.outerSize[0]

        /* eslint-disable no-await-in-loop */
        await label.animate([
          {opacity: 0},
          {opacity: 1},
        ], {
          duration: 100,
          fill: 'forwards',
        }, 300).finished
        /* eslint-enable no-await-in-loop */
      }
      /* eslint-enable no-restricted-syntax */
      return group
    }

    const title = await displayText('Why Sprite?', [1920, 250], {
      anchor: 0.5,
      font: '15rem Arial',
      fillColor: 'white',
    }, 300)

    function showFeatures() {
      const group = new Group()
      group.attr({
        size: [2160, 930],
        pos: [850, 640],
        clip: {
          d: 'M0,0L0,0L0,0L0,0z',
        },
        zIndex: 99,
      })
      fglayer.append(group)
      const features = new Sprite()
      features.attr({
        size: [2160, 930],
        pos: [0, 0],
        bgcolor: {
          vector: [0, 0, 2160, 0],
          colors: [
            {offset: 0, color: '#1EAC61'},
            {offset: 0.4, color: '#1EAC61'},
            {offset: 0.4, color: '#FFF'},
            {offset: 1, color: '#FFF'},
          ],
        },
      })
      group.append(features)

      const label = new Label('特点')
      label.attr({
        anchor: [1, 0],
        pos: [800, 150],
        color: '#fff',
        font: 'bold 128px "宋体"',
      })
      group.append(label)

      const label2 = new Label('FEATURES')
      label2.attr({
        anchor: [1, 0],
        pos: [800, 320],
        color: '#fff',
        font: '80px Arial',
      })
      group.append(label2)

      const label3 = new Label(`- 使用ES6+，面向对象设计和开发
- 支持元素嵌套和事件分发
- 使用缓存提升性能
- 支持 Web Animation API
- 跨平台渲染，支持服务端和小程序
      `)
      label3.attr({
        pos: [1000, 150],
        color: '#000',
        font: '64px "宋体"',
        lineHeight: 120,
      })
      group.append(label3)

      return group
    }

    const featureGroup = showFeatures()

    window.addEventListener('message', (e) => {
      const data = e.data
      if(data && data.namespace === 'reveal') {
        const eventName = data.eventName
        if(eventName === 'fragmentshown') {
          const index = data.state.indexf
          if(index === 0) {
            (async function () {
              huanhuan.animate([
                {x: 1080},
                {x: 2980},
              ], {
                duration: 1000,
                fill: 'forwards',
                easing: 'ease-in',
              })

              guanguan.attr({
                textures: 'guanguan3.png',
              })
              const anim = guanguan.animate([
                {x: 2380},
                {x: 980},
              ], {
                duration: 1000,
                fill: 'forwards',
                easing: 'ease-in',
              })

              title.children.forEach((t) => {
                t.animate([
                  {fillColor: '#333'},
                ], {
                  duration: 1000,
                  fill: 'forwards',
                })
              })

              scene.container.className = 'extend'
              guanguan.on('update', ({renderTime}) => {
                const x1 = guanguan.attr('x'),
                  x2 = huanhuan.attr('x')
                if(x2 - x1 > 0 && x2 - x1 !== featureGroup._clipDX) {
                  featureGroup._clipDX = x2 - x1
                  const l = 916 - (1896 - x1),
                    r = 916 + x2 - 1736
                  const d = `M${l},0L${r},0L${r},${930}L${l},930z`
                  featureGroup.attr({
                    clip: {d},
                  })
                }
              })

              await anim.finished
              guanguan.attr({
                textures: 'guanguan1.png',
              })
            }())
          }
        }
      }
    })
  }())
  </script>
</body>
</html>